package org.vison.framework.doc;

import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.io.Serializable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 属性类型工具类：获取属性的全限定名和简单类型名（支持泛型参数展开）
 */
public class FieldTypeUtils {

    public static TypeInfo getTypeInfo(Type type){
        return new TypeInfo(
                getQualifiedTypeName(type),
                getSimpleTypeName(type)
        );
    }

    public static TypeInfo getTypeInfo(ParameterizedType parameterizedType){
        return new TypeInfo(
                getQualifiedTypeName(parameterizedType),
                getSimpleTypeName(parameterizedType)
        );
    }

    /**
     * 获取属性的类型信息（全限定名 + 简单类型名）
     * @param field 目标属性
     * @return 类型信息封装
     */
    public static TypeInfo getFieldTypeInfo(Field field) {
        if (field == null) {
            throw new IllegalArgumentException("Field cannot be null");
        }
        // 优先处理带注解的类型（JDK 8+），兼容无注解场景
        Type type =  field.getGenericType();
        return new TypeInfo(
                getQualifiedTypeName(type),
                getSimpleTypeName(type)
        );
    }

    /**
     *
     * @param field 目标属性
     * @param actualTypeArgs 所属类的泛型实际参数（普通类可传null/空数组）
     * @return
     */
    public static TypeInfo getFieldTypeInfo(Field field, Type[] actualTypeArgs) {
        if (actualTypeArgs == null || actualTypeArgs.length == 0) {
            return getFieldTypeInfo(field);
        }
        Class<?> declaringClass = field.getDeclaringClass();
        Type fieldType = field.getGenericType();
        Type resolvedType = getType(declaringClass, actualTypeArgs, fieldType);
        return new TypeInfo(
                getQualifiedTypeName(resolvedType),
                getSimpleTypeName(resolvedType)
        );
    }

    private static Type getType(Class<?> declaringClass, Type[] actualTypeArgs, Type fieldType) {
        TypeVariable<? extends Class<?>>[] typeVariables = declaringClass.getTypeParameters();
        Map<TypeVariable<?>, Type> typeVarMap = new HashMap<>();

        // 泛型类：校验并构建 TypeVariable -> 实际类型映射
        if (typeVariables.length > 0) {
            if (actualTypeArgs == null || actualTypeArgs.length != typeVariables.length) {
                throw new IllegalArgumentException(
                        "Field 所属类 " + declaringClass.getName() + " 是泛型类（" + typeVariables.length + "个类型变量），" +
                                "但实际传入 " + (actualTypeArgs == null ? 0 : actualTypeArgs.length) + " 个实际类型参数"
                );
            }
            for (int i = 0; i < typeVariables.length; i++) {
                typeVarMap.put(typeVariables[i], actualTypeArgs[i]);
            }
        }
        Type resolvedType = resolveTypeVariable(fieldType, typeVarMap);
        return resolvedType;
    }


    /**
     * 获取类型的全限定名（包含完整包路径，泛型参数展开）
     * @param type 目标类型（支持所有合法属性类型）
     * @return 全限定名（如 java.util.List<java.lang.String>、com.example.Pojo[]）
     */
    private static String getQualifiedTypeName(Type type) {
        return resolveTypeName(type, true);
    }

    /**
     * 获取类型的简单类型名（简化包路径，泛型参数展开）
     * @param type 目标类型（支持所有合法属性类型）
     * @return 简单类型名（如 List<String>、Pojo[]）
     */
    private static String getSimpleTypeName(Type type) {
        return resolveTypeName(type, false);
    }

    private static Type resolveTypeVariable(Type type, Map<TypeVariable<?>, Type> typeVarMap) {
        if (type instanceof AnnotatedType) {
            AnnotatedType annotatedType = (AnnotatedType) type;
            return resolveTypeVariable(annotatedType.getType(), typeVarMap);
        }
        if (type instanceof TypeVariable<?>) {
            TypeVariable<?> typeVar = (TypeVariable<?>) type;
            return typeVarMap.getOrDefault(typeVar, type);
        }
        if (type instanceof ParameterizedType) {
            ParameterizedType paramType = (ParameterizedType) type;
            Type[] resolvedArgs = Arrays.stream(paramType.getActualTypeArguments())
                    .map(arg -> resolveTypeVariable(arg, typeVarMap))
                    .toArray(Type[]::new);
            return ParameterizedTypeImpl.make(paramType.getRawType().getClass(), resolvedArgs, paramType.getOwnerType());
        }
        if (type instanceof GenericArrayType) {
            GenericArrayType arrayType = (GenericArrayType) type;
            Type resolvedComponent = resolveTypeVariable(arrayType.getGenericComponentType(), typeVarMap);
            return GenericArrayTypeImpl.make(resolvedComponent);
        }
        if (type instanceof WildcardType) {
            WildcardType wildcardType = (WildcardType) type;
            Type[] resolvedUpper = Arrays.stream(wildcardType.getUpperBounds())
                    .map(bound -> resolveTypeVariable(bound, typeVarMap))
                    .toArray(Type[]::new);
            Type[] resolvedLower = Arrays.stream(wildcardType.getLowerBounds())
                    .map(bound -> resolveTypeVariable(bound, typeVarMap))
                    .toArray(Type[]::new);
            // todo: 处理通配符类型（? extends T、? super T）
        }
        return type;
    }

    /**
     * 核心解析逻辑：根据是否需要全限定名，递归解析类型
     * @param type 目标类型
     * @param qualified 是否需要全限定名（true=包含包路径，false=简化）
     * @return 解析后的类型名
     */
    private static String resolveTypeName(Type type, boolean qualified) {
        // 1. 处理带注解的类型（JDK 8+）：直接取其底层类型
        if (type instanceof AnnotatedType) {
            return resolveTypeName(((AnnotatedType) type).getType(), qualified);
        }

        // 2. 处理 Class 类型（原始类型、基本类型、普通数组）
        if (type instanceof Class<?>) {
            Class<?> clazz = (Class<?>) type;
            // 基本类型（如 int、boolean）
            if (clazz.isPrimitive()) {
                return clazz.getName();
            }
            // 普通数组（如 String[]、int[]）
            if (clazz.isArray()) {
                String componentName = resolveTypeName(clazz.getComponentType(), qualified);
                return componentName + "[]";
            }
            // 普通类/接口（如 String、User）
            return qualified ? clazz.getName() : clazz.getSimpleName();
        }

        // 3. 处理参数化类型（如 List<String>、Map<Integer, User>）
        if (type instanceof ParameterizedType) {
            ParameterizedType paramType = (ParameterizedType) type;
            // 获取原始类型（如 List、Map）
            String rawTypeName = resolveTypeName(paramType.getRawType(), qualified);
            // 解析泛型参数（如 String、Integer）
            String typeArgs = Arrays.stream(paramType.getActualTypeArguments())
                    .map(arg -> resolveTypeName(arg, qualified))
                    .reduce((a, b) -> a + ", " + b)
                    .orElse("");
            return rawTypeName + "<" + typeArgs + ">";
        }

        // 4. 处理通配符类型（如 ?、? extends Number、? super String）
        if (type instanceof WildcardType) {
            WildcardType wildcardType = (WildcardType) type;
            Type[] upperBounds = wildcardType.getUpperBounds();
            Type[] lowerBounds = wildcardType.getLowerBounds();

            // 上界（如 ? extends Number）：默认上界是 Object，无需显示
            if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class)) {
                String upper = resolveTypeName(upperBounds[0], qualified);
                return "? extends " + upper;
            }
            // 下界（如 ? super String）：下界默认是 null，必须显示
            if (lowerBounds.length > 0) {
                String lower = resolveTypeName(lowerBounds[0], qualified);
                return "? super " + lower;
            }
            // 无边界通配符（如 ?）
            return "?";
        }

        // 5. 处理泛型数组类型（如 T[]、List<String>[]）
        if (type instanceof GenericArrayType) {
            GenericArrayType arrayType = (GenericArrayType) type;
            String componentName = resolveTypeName(arrayType.getGenericComponentType(), qualified);
            return componentName + "[]";
        }

        // 6. 处理类型变量（如泛型类中的 T，仅在泛型类属性中出现）
        if (type instanceof TypeVariable<?>) {
            TypeVariable<?> typeVar = (TypeVariable<?>) type;
            // 类型变量的上界（如 T extends Number & Serializable）
            String bounds = Arrays.stream(typeVar.getBounds())
                    .map(bound -> resolveTypeName(bound, qualified))
                    .reduce((a, b) -> a + " & " + b)
                    .orElse("");
            return typeVar.getName() + (bounds.isEmpty() ? "" : " extends " + bounds);
        }

        // 兜底：未知类型（理论上不会触发，覆盖所有合法场景）
        return type.toString();
    }

    /**
     * 类型信息封装类：包含全限定名和简单类型名
     */
    public static class TypeInfo implements Serializable {
        private final String qualifiedName;
        private final String simpleName;

        public TypeInfo(String qualifiedName, String simpleName) {
            this.qualifiedName = qualifiedName;
            this.simpleName = simpleName;
        }

        public String getQualifiedName() {
            return qualifiedName;
        }

        public String getSimpleName() {
            return simpleName;
        }

        @Override
        public String toString() {
            return "TypeInfo{" +
                    "qualifiedName='" + qualifiedName + '\'' +
                    ", simpleName='" + simpleName + '\'' +
                    '}';
        }
    }

    // ------------------------------ 测试辅助类（与工具类同包，供测试使用） ------------------------------
    /**
     * 测试用 Bean：包含各种类型的属性
     */
    public static class TestBean {
        // 普通类
        public String username;
        // 基本类型
        public int age;
        // 普通数组
        public String[] tags;
        // JDK 泛型
        public List<String> stringList;
        // 自定义泛型
        public List<Pojo> pojoList;
        // 嵌套泛型
        public Map<Integer, List<User>> userMap;
        // 通配符泛型
        public List<? extends Number> numberList;
        // 泛型数组
        public List<Pojo>[] pojoArray;
        // 带注解的泛型（JDK 8+）
        public List<@Nullable String> annotatedList;
    }

    /**
     * 泛型类（用于测试 TypeVariable）
     */
    public static class GenericBean<T extends Number & Serializable> {
        public T value;
    }

    public static class Result<T> {
        public T data;
    }

    public static class Page<T> {
        public List<T> list;
    }

    /**
     * 自定义POJO（用于测试自定义泛型）
     */
    public static class Pojo {}

    /**
     * 自定义POJO（用于测试嵌套泛型）
     */
    public static class User {}

    /**
     * 自定义类型注解（JDK 8+）
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE_USE})
    public @interface Nullable {}
}